﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UBlockly.UI;
using UBlockly.Scriptable;
using System;

namespace UBlockly.Util
{
    public static class UTool
    {
        public static List<FunctionBlockAssist> TryParse<T>() where T : UBlockly.IBlockApi
        {
            var methods = typeof(T).GetMethods();
            List<FunctionBlockAssist> list = new List<FunctionBlockAssist>();
            foreach (var item in methods)
            {
                var bfa = item.GetCustomAttributes(typeof(BlockFunctionAttribute), false);
                if (bfa == null || bfa.Length != 1)
                {
                    continue;
                }
                string deff = GetSupportTypeName(item.ReturnType);
                if (string.IsNullOrEmpty(deff))
                {
                    continue;
                }
                FunctionBlockAssist ba = new FunctionBlockAssist();
                ba.FunctionDesc = Common.GetEnumDescription((BlockFunctionDefine)((BlockFunctionAttribute)bfa[0]).Id);
                deff += " ";
                deff += item.Name;
                var param = item.GetParameters();
                if (param == null || param.Length == 0 || param.Length == 1 || (param.Length == 2 && param[1].ParameterType == typeof(System.Action)))
                {
                    if (param == null || param.Length == 0 || param[0].ParameterType == typeof(System.Action))
                        deff += "()";
                    else
                    {
                        deff += "({0} {1})";
                        deff = string.Format(deff, GetSupportTypeName(param[0].ParameterType), param[0].Name);
                    }
                }
                else
                {

                    Debug.LogError("eeeeee:" + deff + " " + param[0].Name);
                    continue;
                }
                if (((BlockFunctionAttribute)bfa[0]).DefaultParams != null)
                {
                    int count = ((BlockFunctionAttribute)bfa[0]).DefaultParams.Length;
                    ba.defaultParams = new KeyValuePair<string, object>[count];
                    ((BlockFunctionAttribute)bfa[0]).DefaultParams.CopyTo(ba.defaultParams, 0);
                }
                ba.FunctionDefineStr = deff;
                list.Add(ba);
            }
            return list;
        }

        public static string GetSupportTypeName(System.Type type)
        {
            string deff = "";
            if (type == typeof(void)) deff = "void";
            if (type == typeof(bool)) deff = "bool";
            if (type == typeof(int)) deff = "int";
            if (type == typeof(string)) deff = "string";
            return deff;
        }

        public static string ParseFuncName(string funcDefineStr)
        {
            var len = funcDefineStr.IndexOf('(') - funcDefineStr.IndexOf(" ");
            var name = funcDefineStr.Substring(funcDefineStr.IndexOf(" ") + 1, len - 1);
            return name.Trim();
        }

        public static ILFuncType ParseFuncType(string funcDefineStr)
        {
            var len = funcDefineStr.IndexOf(")") - funcDefineStr.IndexOf("(");
            var param = funcDefineStr.Substring(funcDefineStr.IndexOf("(") + 1, len - 1);
            if (string.IsNullOrEmpty(param))
                param = "void";
            var resultstr = "";
            if (funcDefineStr.StartsWith("void "))
                resultstr = "void";
            if (funcDefineStr.StartsWith("bool"))
                resultstr = "bool";
            if (funcDefineStr.StartsWith("int"))
                resultstr = "int";
            if (funcDefineStr.StartsWith("string"))
                resultstr = "string";
            if (resultstr != "")
            {
                return ParseFuncType(resultstr, param);
            }
            return ILFuncType.NoDefine;
        }

        public static ILFuncType ParseFuncType(string resultStr, string paramStr)
        {
            paramStr = paramStr.Trim();
            switch (resultStr)
            {
                case "void":
                    if (paramStr.StartsWith("void"))
                        return ILFuncType.VoidVoid;
                    else if (paramStr.StartsWith("bool"))
                        return ILFuncType.VoidBool;
                    else if (paramStr.StartsWith("int"))
                        return ILFuncType.VoidInt;
                    else if (paramStr.StartsWith("string"))
                        return ILFuncType.VoidString;
                    break;
                case "bool":
                    if (paramStr.StartsWith("void"))
                        return ILFuncType.BoolVoid;
                    else if (paramStr.StartsWith("bool"))
                        return ILFuncType.BoolBool;
                    else if (paramStr.StartsWith("int"))
                        return ILFuncType.BoolInt;
                    else if (paramStr.StartsWith("string"))
                        return ILFuncType.BoolString;
                    break;
                case "int":
                    if (paramStr.StartsWith("void"))
                        return ILFuncType.IntVoid;
                    else if (paramStr.StartsWith("bool"))
                        return ILFuncType.IntBool;
                    else if (paramStr.StartsWith("int"))
                        return ILFuncType.IntInt;
                    else if (paramStr.StartsWith("string"))
                        return ILFuncType.IntString;
                    break;
                case "string":
                    if (paramStr.StartsWith("void"))
                        return ILFuncType.StringVoid;
                    else if (paramStr.StartsWith("bool"))
                        return ILFuncType.StringBool;
                    else if (paramStr.StartsWith("int"))
                        return ILFuncType.StringInt;
                    else if (paramStr.StartsWith("string"))
                        return ILFuncType.StringString;
                    break;
                default:
                    break;
            }
            return ILFuncType.NoDefine;
        }
    }
}
